## k近邻算法应用
# 其核心思想是：如果一个样本在特征空间中的K个最相似（即距离最近）的样本中的大多数属于某一个类别，
# 则该样本也属于这个类别。KNN算法不需要训练过程，而是直接基于训练数据集对新样本进行分类或回归。

# 是 Python 中用于科学计算的一个基础库，提供了大量的数学函数和操作，特别适合处理大型多维数组和矩阵。
import numpy as np
#matplotlib 是一个广泛使用的绘图库，用于创建静态、动画和交互式可视化图表。
# pyplot 是 matplotlib 中的一个模块，提供了类似于 MATLAB 的绘图接口，方便用户快速创建各种图表。
import matplotlib.pyplot as plt
# sklearn 是 scikit-learn 的简写，一个流行的机器学习库。
# neighbors 是 scikit-learn 中的一个模块，包含了与最近邻算法相关的类和函数。
# KNeighborsClassifier：这是一个用于分类任务的 K近邻算法实现。
from sklearn.neighbors import KNeighborsClassifier

import operator

def classifity0():
    # 准备二维数据
    X = np.array([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]])
    y = np.array([0, 0, 1, 1, 1])
    # 创建k模型实例，考虑最近的 3 个邻居。n_neighbors 是 K近邻算法中的 K 值，决定了在分类时参考的邻居数量。
    model = KNeighborsClassifier(n_neighbors=3)
    # 模拟训练集
    # x:这是训练数据的特征矩阵，,y:训练目标
    model.fit(X, y)
    # 对新样本进行预测
    new_sample = np.array([[2.5, 3.5]])
    prediction = model.predict(new_sample)
    print("Prediction:", prediction)
    # 对结果进行可视化
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
    plt.scatter(new_sample[:, 0], new_sample[:, 1], marker='x', c='red')
    plt.xlabel('Feature 1')
    plt.ylabel('Feature 2')
    plt.title('KNN Classifier')
    plt.show()

def classifity1():
    # 创建二维数组，要梳理出来，x轴代表：打斗镜头，y轴代表接吻镜头
    group = np.array([[1, 101], [5, 89], [108, 5], [115, 8]])
    labels = ['爱情片', '爱情片', '动作片', '动作片']
    print(group)
    print(labels)
    return group, labels


"""
函数说明:kNN算法,分类器

Parameters:
    inX - 用于分类的数据(测试集)
    dataSet - 用于训练的数据(训练集)
    labes - 分类标签
    k - kNN算法参数,选择距离最小的k个点
Returns:
    sortedClassCount[0][0] - 分类结果
"""
def classify1(inX, dataSet, labels, k):
    # numpy函数shape[0]返回dataSet的行数
    dataSetSize = dataSet.shape[0]
    # 在列向量方向上重复inX共1次(横向)，行向量方向上重复inX共dataSetSize次(纵向)
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    # 二维特征相减后平方
    sqDiffMat = diffMat ** 2
    # sum()所有元素相加，sum(0)列相加，sum(1)行相加
    sqDistances = sqDiffMat.sum(axis=1)
    # 开方，计算出距离
    distances = sqDistances ** 0.5
    # 返回distances中元素从小到大排序后的索引值
    sortedDistIndices = distances.argsort()
    # 定一个记录类别次数的字典
    classCount = {}
    for i in range(k):
        # 取出前k个元素的类别
        voteIlabel = labels[sortedDistIndices[i]]
        # dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。
        # 计算类别次数
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    # python3中用items()替换python2中的iteritems()
    # key=operator.itemgetter(1)根据字典的值进行排序
    # key=operator.itemgetter(0)根据字典的键进行排序
    # reverse降序排序字典
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1),
                              reverse=True)
    # 返回次数最多的类别,即所要分类的类别
    return sortedClassCount[0][0]

if __name__ == '__main__':
    # 创建数据集
    group, labels = classifity1()
    # 测试集
    test = [101, 20]
    # kNN分类
    test_class = classify1(test, group, labels, 3)
    # 打印分类结果
    print(test_class)

